<template>
  <div v-if="dialogFormVisible" class="m-wangEditor">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editorRef"
      :defaultConfig="toolbarConfig"
      :mode="mode"
    />
    <Editor
      class="editor-content'"
      style="height: 300px; overflow-y: hidden"
      v-model="valueHtml"
      :defaultConfig="editorConfig"
      :mode="mode"
      @onCreated="handleCreated"
    />
  </div>
</template>
<script lang="ts" setup>
  // 引入 wangEditor
  import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
  import '@wangeditor/editor/dist/css/style.css' // 引入 css
  import { onBeforeUnmount, shallowRef, ref, computed, getCurrentInstance, onMounted } from 'vue'
  import { useUserStore } from '@/store/modules/user'

  const baseUrl = import.meta.env.VITE_APP_BASE_API
  const { proxy }: any = getCurrentInstance()
  const UserStore = useUserStore()
  let editors = null
  const dialogFormVisible = ref(true)
  // 编辑器实例，必须用 shallowRef
  const editorRef = shallowRef()
  const toolbarConfig = {}
  type InsertFnType = (url: string, alt: string, href: string) => void
  type InsertFnVideoType = (url: string, poster: string) => void
  const editorConfig = {
    placeholder: '请输入内容...',
    MENU_CONF: {
      // 配置默认字号
      // 配置上传图片
      uploadImage: {
        // 请求路径
        server: baseUrl + '/common/upload',
        // 后端接收的文件名称
        fieldName: 'file',
        maxFileSize: 1 * 1024 * 1024, // 1M
        // 上传的图片类型
        allowedFileTypes: ['image/*'],
        // 小于该值就插入 base64 格式（而不上传），默认为 0
        base64LimitSize: 10 * 1024, // 10MB
        // 自定义插入返回格式【后端返回的格式】
        customInsert(res: any, insertFn: InsertFnType) {
          console.log('customInsert')
          if (res.code != 200) {
            proxy.$modal.msgError('上传文件失败，' + res.message)
            return
          }
          // 从 res 中找到 url alt href ，然后插入图片
          insertFn(res.url, null, null)
        },
        // 携带的数据
        meta: {},
        // 将 meta 拼接到 url 参数中，默认 false
        metaWithUrl: false,
        withCredentials: true,
        // headers
        headers: {
          Authorization: UserStore.token,
        },
        // 单个文件上传成功之后
        onSuccess(file, res) {
          if (res.code == 200) {
            proxy.$modal.msgSuccess(`${file.name} 上传成功`)
            return
          } else {
            proxy.$modal.msgWarning(`${file.name} 上传出了点异常`)
            return
          }
        },
        // 单个文件上传失败
        onFailed(file, res) {
          console.log(res)
          proxy.$modal.msgError(`${file.name} 上传失败`)
        },
        // 上传错误，或者触发 timeout 超时
        onError(file, err, res) {
          console.log(err, res)
          proxy.$modal.msgError(`${file.name} 上传出错`)
        },
      },
      // 上传视频
      uploadVideo: {
        server: baseUrl + '/common/upload',
        // form-data fieldName ，默认值 'wangeditor-uploaded-video'
        fieldName: 'file',
        // 单个文件的最大体积限制，默认为 10M
        maxFileSize: 100 * 1024 * 1024, // 5M
        // 最多可上传几个文件，默认为 5
        maxNumberOfFiles: 3,
        // 选择文件时的类型限制，默认为 ['video/*'] 。如不想限制，则设置为 []
        allowedFileTypes: ['video/*'],
        // 自定义上传参数，例如传递验证的 token 等。参数会被添加到 formData 中，一起上传到服务端。
        meta: {},
        // 将 meta 拼接到 url 参数中，默认 false
        metaWithUrl: false,
        // 自定义增加 http  header
        headers: {
          Authorization: UserStore.token,
        },
        // 跨域是否传递 cookie ，默认为 false
        withCredentials: true,
        // 超时时间，默认为 30 秒
        timeout: 15 * 1000, // 15 秒
        // 视频不支持 base64 格式插入
        // 自定义插入视频
        customInsert(res: any, insertFn: InsertFnType) {
          // TS 语法
          // res 即服务端的返回结果
          if (res.code != 200) {
            proxy.$modal.msgError('上传文件失败，' + res.message)
            return
          }
          // 从 res 中找到 url poster ，然后插入视频
          insertFn(res.url, null)
        },
        // 上传之前触发
        onBeforeUpload(file: File) {
          // TS 语法
          // file 选中的文件，格式如 { key: file }

          return file

          // 可以 return
          // 1. return file 或者 new 一个 file ，接下来将上传
          // 2. return false ，不上传这个 file
        },

        // 上传进度的回调函数
        onProgress(progress: number) {
          // TS 语法
          // onProgress(progress) {       // JS 语法
          // progress 是 0-100 的数字
          console.log('progress', progress)
        },

        // 单个文件上传成功之后
        onSuccess(file: File, res: any) {
          // TS 语法
          // onSuccess(file, res) {          // JS 语法
          console.log(`${file.name} 上传成功`, res)
        },

        // 单个文件上传失败
        onFailed(file: File, res: any) {
          // TS 语法
          // onFailed(file, res) {          // JS 语法
          console.log(`${file.name} 上传失败`, res)
        },

        // 上传错误，或者触发 timeout 超时
        onError(file: File, err: any, res: any) {
          // TS 语法
          // onError(file, err, res) {               // JS 语法
          console.log(`${file.name} 上传出错`, err, res)
        },
      },
    },
  }

  const loading = ref(false)

  // 内容 HTML
  const mode = ref('default')
  let emit = defineEmits(['update:modelValue'])
  let props = defineProps({
    modelValue: String,
    editorConfig: {
      default: () => ({
        placeholder: '请输入内容...',
      }),
      type: Object,
    },
  })

  const getEditorData = () => {
    // 通过代码获取编辑器内容
    let data = editors.txt.html()
    alert(data)
  }

  const handleCreated = (editor) => {
    editorRef.value = editor // 记录 editor 实例，重要！
  }

  const valueHtml = computed({
    get() {
      return props.modelValue
    },
    set(val) {
      // 防止富文本内容为空时，校验失败
      if (editorRef.value.isEmpty()) val = ''
      emit('update:modelValue', val)
    },
  })

  // 组件销毁时，也及时销毁编辑器
  onBeforeUnmount(() => {
    // 调用销毁 API 对当前编辑器实例进行销毁
    console.log('销毁')
    const editor = editorRef.value
    if (editor == null) {
      return
    }
    editor.destroy()
  })

  const show = () => {
    dialogFormVisible.value = true
  }

  const noShow = () => {
    dialogFormVisible.value = false
  }

  onMounted(() => {
    setTimeout(() => {
      valueHtml.value = props.modelValue
    }, 1500)
  })

  defineExpose({
    show,
    noShow,
  })
</script>
<style lang="scss" scoped>
  .m-wangEditor {
    z-index: 99;
    width: 100%;
    border: 1px solid #cccccc;

    .editor-toolbar {
      border-bottom: 1px solid #cccccc;
    }

    .editor-content {
      overflow-y: hidden;
    }
  }
</style>
